import { InboxOutlined } from '@ant-design/icons';
import { useMutation } from '@tanstack/react-query';
import { Col, Empty, Flex, Image, message, Row, Skeleton, Spin, Upload, UploadProps } from 'antd';
import { isString } from 'lodash';
import { memo, useRef, useState } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader.js';
import { v4 } from 'uuid';
import { playVideo, uploadVideo } from './api';
import { three_module_style } from './style';

const { Dragger } = Upload;

const ThreeModule = () => {
  // const [getGltfKey] = useState(`playVideo_${v4()}`)
  const containerRef = useRef<HTMLDivElement>(null);
  const [showImage, setShowImage] = useState<boolean>(false);
  // const { data: gltfRes } = useQuery({
  //   queryKey: [getGltfKey],
  //   queryFn: () => getGltf()
  // });

  const loadModal = () => {
    const container = containerRef.current;

    if (container) {
      const scene = new THREE.Scene();
      const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
      const renderer = new THREE.WebGLRenderer();
      const controls = new OrbitControls(camera, renderer.domElement);
      const clock = new THREE.Clock();
      const light = new THREE.PointLight(0xffffff, 1000, 1000);
      const gltfLoader = new GLTFLoader();
      const dracoLoader = new DRACOLoader();
      let mixer: THREE.AnimationMixer | null = null;

      light.position.set(10, 10, 10);
      scene.add(light);
      scene.background = new THREE.Color('#E1FFFF');
      // camera.position.z = 5;
      camera.position.x = 3;
      camera.position.y = 4;
      camera.position.z = 5;
      renderer.setSize(container.clientWidth, 600);
      gltfLoader.setDRACOLoader(dracoLoader)
      container.innerHTML = '';
      container.appendChild(renderer.domElement);
      controls.update();

      let counter = 0
      const animate = () => {
        requestAnimationFrame( animate );
        if (mixer) {
          const delta = clock.getDelta();

          mixer.update(delta);
        }
        counter++;
        camera.position.x += counter >= 200 ? 0.0001 : -0.0001;
        camera.position.y += counter >= 200 ? 0.0001 : -0.0001;
        camera.position.z += counter >= 200 ? 0.0001 : -0.0001;
        if (counter>=400) {
          counter = 0;
        }
        renderer.render( scene, camera );
      };

      gltfLoader.load(
        '/gltf/lotus_and_leaf_-_hoa_sen_-_tvc/scene.gltf',
        // ?? gltfRes?.result ?? '/gltf/phoenix_bird/scene.gltf',
        (gltf: { scene: any; animations: THREE.AnimationClip[]; }) =>{
          const model = gltf.scene;

          model.position.set(6, 3, 4.5);
          // model.position.set(1, -5, 1);
          // model.position.set(1, -1.5, -3);
          // model.scale.set(-0.4, -0.4, 0.4);
          model.scale.set(1, 1, 1);
          scene.add(model);
          mixer = new THREE.AnimationMixer(model);
          // mixer.clipAction(gltf.animations[0]).play();
          animate();
          setShowImage(false);
        },
        undefined,
        (error: any) => {
          console.error( error );
        }
      );
    }
  };

  const { mutate: playMutate } = useMutation({
    mutationFn: playVideo
  });

  const { data, isPending, mutate: uploadMutate } = useMutation({
    mutationFn: uploadVideo,
    onSuccess(res) {
      if (isString(res?.result?.path)) {
        message.destroy();
        message.success('上传成功');
        if (res.result.isVideo)  {
          playMutate({path: res.result.path});
        } else {
          loadModal();
          setShowImage(true);
        }
      }
    },
  });

  const isVideo = Boolean(data?.result?.isVideo);

  const uploadProps: UploadProps = {
    name: 'file',
    accept: '.mp4, .jpg',
    multiple: false,
    showUploadList: false,
    customRequest: (options) => {
      const container = containerRef.current;

      if (container) {
        container.innerHTML = '';
      }
      uploadMutate({ file: options.file as File });
    }
  };

  return (
    <Row className={three_module_style} gutter={[16, 16]}>
      <Col span={6}>
        <Flex vertical gap={16}>
          <Dragger {...uploadProps} key={data?.result?.id ?? v4()}>
            <Spin spinning={isPending}>
              <p className='ant-upload-drag-icon'>
                <InboxOutlined />
              </p>
              <p className='ant-upload-text'>单击或拖动文件到此区域进行上传</p>
              <p className='ant-upload-hint'>支持单次或批量上传。</p>
            </Spin>
          </Dragger>
          {!isVideo && isString(data?.result?.path) && (<Image height={400 - 16} src={data.result.path} />)}
        </Flex>
      </Col>
      <Col span={18}>
        {
          data?.result?.path ?
          (isVideo && (<video className='video' src={data.result.path} autoPlay controls></video>)) :
          (<Empty description={false} />)
        }
        {showImage && (<Skeleton active />)}
        <div ref={containerRef}></div>
      </Col>
    </Row>
  )
};

export default memo(ThreeModule);